﻿using System;
using System.Net;

namespace Hydra.Shell.Attributes
{
    [System.AttributeUsage(System.AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
    public sealed class ProvideServiceAttribute : RegistrationAttribute
    {
        private string _name;
        private System.Guid _serviceGuid;
        private System.Type _serviceType = null;

        public ProvideServiceAttribute(Type serviceType) : this((object) serviceType)
        {
        }

        public ProvideServiceAttribute(string serviceTypeName) : this((object) serviceTypeName)
        {
        }

        public ProvideServiceAttribute(object serviceType)
        {
            if (serviceType is string)
            {
                this._serviceGuid = new System.Guid((string)((string)serviceType));
            }
            else if (serviceType is System.Type)
            {
                this._serviceType = (System.Type)serviceType;
                this._serviceGuid = this._serviceType.GUID;
                this._name = this._serviceType.Name;
            }
            else
            {
                if (!(serviceType is System.Guid))
                {
                    throw new System.ArgumentException(string.Format("Invalid Factory Type", new object[] { serviceType }));
                }
                this._serviceGuid = (System.Guid)serviceType;
            }
        }

        public override void Register(RegistrationAttribute.RegistrationContext context)
        {
            using (RegistrationAttribute.Key key = context.CreateKey(this.ServiceRegKey))
            {
                key.SetValue(string.Empty, context.ComponentType.GUID.ToString("B"));
                key.SetValue("Name", this.ServiceName);
            }
        }

        public override void Unregister(RegistrationAttribute.RegistrationContext context)
        {
            context.RemoveKey(this.ServiceRegKey);
        }

        public System.Type Service
        {
            get
            {
                return this._serviceType;
            }
        }

        public string ServiceName
        {
            get
            {
                return this._name;
            }
            set
            {
                this._name = value;
            }
        }

        private string ServiceRegKey
        {
            get
            {
                return string.Format(System.Globalization.CultureInfo.InvariantCulture, @"Services\{0}", new object[] { this.ServiceType.ToString("B") });
            }
        }

        public System.Guid ServiceType
        {
            get
            {
                return this._serviceGuid;
            }
        }
    }
}
